/*
 *  Copyright 2019-2020
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package cn.cdeden.knowledge.utils;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import io.undertow.server.handlers.form.FormData;
import io.undertow.util.BadRequestException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileItemFactory;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.awt.geom.Rectangle2D;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * File工具类，扩展 hutool 工具包
 *
 * @author
 * @date 2018-12-27
 */
@Slf4j
public class FileUtil extends cn.hutool.core.io.FileUtil {

    public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;




    /**
     * @param fileName
     * @Description // 处理 文件 是否有特殊符号 称处理 抛出异常
     **/
    public static String fileNameProcessingException(String fileName) {
        return fileNameProcessing(fileName, false);
    }


    /**
     * @param fileName
     * @param b        true静默处理   false 抛出异常
     * @return java.lang.String
     * @author Yu.
     * @Description // 处理 文件 是否有特殊符号 称处理
     * @Date 2023/12/13 13:45
     **/
    public static String fileNameProcessing(String fileName, boolean b) {
//       检查文件长度文件的长都
        if (fileName.length() > 200) {
            if (b) {
                fileName = fileName.substring(0, 200);
            } else {
                throw new RuntimeException("超过文件命名规则上限");
//                throw new BadRequestException("超过文件命名规则上限");
            }
        }
        //不同系统有不同的 命明规则
//        String os = System.getProperty("os.name");
//        if(os.toLowerCase().startsWith(ElAdminConstant.WIN)) { // 处理特殊符号
//            fileName = fileName.replaceAll("[\\/:*?\"<>|]", "");
//        }else {
//            fileName = fileName.replaceAll("[@#$%^&*\\/]", "");
        String url = "[@#$%^&*\\/:*?\"<>|]";
        if (fileName.matches(url)) {
            if (b) {
                fileName = fileName.replaceAll("", "");
            } else {
                throw new RuntimeException("超过文件命名规则上限");
//                throw new BadRequestException("超过文件命名规则上限");
            }
        }


//        }
        return fileName;
    }


    public static String getSizeUnit(Long size) {
        // 将size转换为double类型，以便进行数学计算
        Long val = size;
        // 检查大小是否为NaN，尽管在long类型中这不可能，但为了保持逻辑完整性，这里假设val为double类型
        if (Double.isNaN(val)) {
            return "-";
        }
        // 检查大小是否为负数
        if (val < 0) {
            return "-";
        }

        // 定义文件大小单位数组
        String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
        // 计算当前大小对应的单位指数，即确定大小处于哪个单位范围内
        int temp = (int) Math.floor(Math.log(val) / Math.log(2));
        // 确保单位指数不小于0
        if (temp < 1) {
            temp = 0;
        }
        // 计算并选择合适的单位索引，防止数组越界
        int unitIndex = Math.min(temp / 10, units.length - 1);
        // 根据选中的单位，计算转换后的值
        double val1 = val / Math.pow(2, 10 * unitIndex);

        // 格式化输出，保留两位小数
        DecimalFormat df = new DecimalFormat("#.##");
        String formattedVal = df.format(val1);

        // 返回格式化后的大小和单位
        return formattedVal + " " + units[unitIndex];
    }

    /**
     * 导出excel
     */
    public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response, String fileName, String header) throws IOException {
        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        File file = new File(tempPath);
        try {
            BigExcelWriter writer = ExcelUtil.getBigWriter(file);

            Integer columnCount = list.get(0).size(); // 获取列数
            SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();

            // 判断是否有header，如果有则先处理header的合并与样式
            if (StringUtils.isNotBlank(header)) {
                int lastColumnIndex = columnCount - 1; // 计算最后一列的索引
                // 创建或获取默认样式
                CellStyle defaultCellStyle = writer.getStyleSet().getHeadCellStyle();
                defaultCellStyle.setWrapText(true); // 设置自动换行
                CellStyle mergeCellStyle = writer.getWorkbook().createCellStyle();
                mergeCellStyle.cloneStyleFrom(defaultCellStyle); // 复制默认样式
                mergeCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); // 设置背景颜色为白色
                mergeCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 设置填充模式为实心填充


                // 写入表头行
                writer.writeRow(list.get(0), false);
                // 插入一行在最上面

//                writer.insertRow(writer, startRow, rows, sheet,false);
                // 合并表头单元格并应用样式
                writer.merge(0, 0, 0, lastColumnIndex, header, mergeCellStyle);

                // 设置表头行高
                writer.setRowHeight(0, 100);
//                writer.setC
            }


            // 一次性写出内容，使用默认样式，强制输出标题
            writer.write(list, true);

            // 自适应列宽并支持中文
            sheet.trackAllColumnsForAutoSizing();
            sizeChineseColumn02(sheet,columnCount,header);




            // 设置响应参数
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            //.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

            try (ServletOutputStream out = response.getOutputStream()) {
                writer.flush(out, true);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (file.exists()) {
                file.delete(); // 删除临时文件
            }
        }
    }


    private static void sizeChineseColumn02(SXSSFSheet sheet, int columnCount,String header) {
        for (int columnNum = 0; columnNum < columnCount; columnNum++) {
            int columnWidth = 0;
            int rowNum01 = StringUtils.isBlank(header) ? 0 : 1;
            for (int rowNum = rowNum01; rowNum <= sheet.getLastRowNum(); rowNum++) {
                SXSSFRow currentRow = sheet.getRow(rowNum);
                if (currentRow != null) {
                    SXSSFCell currentCell = currentRow.getCell(columnNum);
                    if (currentCell != null) {
                        int length = 0;
                        if (currentCell.getCellType() == CellType.STRING) {
                            // 计算字符串列的宽度
                            length = currentCell.getStringCellValue().length() +
                                currentCell.getStringCellValue().getBytes().length -
                                currentCell.getStringCellValue().length();
                        } else if (currentCell.getCellType() == CellType.NUMERIC) {
                            // 计算数字列的宽度
                            length = currentCell.toString().length();
                        }
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }
            // 计算最终列宽，调整补偿像素
            int finalWidth = (columnWidth + 2) * 256; // +2是为了增加少许的额外空间
            finalWidth = Math.min(finalWidth, 65280); // 限制最大宽度
            sheet.setColumnWidth(columnNum, finalWidth);
        }
    }

    /**
     * 将输入流转换成MultipartFile
     * @param inputStream
     * @param fileName     文件全称（包括后缀）
     * @return
     */
    public static MultipartFile InputStreamToMultipartFile(InputStream inputStream,String fileName) {
        if (inputStream == null)throw new RuntimeException("文件流为空！");
        try {
            MockMultipartFile mockMultipartFile = new MockMultipartFile(fileName,inputStream);;
            return mockMultipartFile;
        }catch (IOException e){
            log.error("文件流转换MultipartFile异常",e);
            throw new RuntimeException("文件流转换MultipartFile异常");
        }

    }

    /**
     * 检验后缀是否符合dify上传文件格式
     * @param suffix
     * @return
     */
    public static Boolean checkSuffix(String suffix) {
        if (StringUtils.isBlank(suffix)) {
            return false;
        } else {
            if (suffix.equals("txt") || suffix.equals("markdown") || suffix.equals("md")
                || suffix.equals("pdf") || suffix.equals("html") || suffix.equals("xlsx")
                || suffix.equals("xls") || suffix.equals("docx") || suffix.equals("csv")
                || suffix.equals("htm")) {
                return true;
            } else {
                return false;
            }
        }
    }

    public static File createDocx(String dirFile) {
        // 创建一个新的Word文档
        XWPFDocument document = new XWPFDocument();

        // 创建一个段落
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.setText("Hello, World!");

        // 保存文档到文件
        try {
            FileOutputStream out = new FileOutputStream(dirFile);
            document.write(out);
            out.close();
            System.out.println("Word文件创建成功！");
        } catch (Exception e) {
            System.out.println("创建Word文件时发生错误：" + e.getMessage());
        }
        return new File(dirFile);
    }

    public static File createExcel(String dirFile) {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("Sheet1");
        Row row = sheet.createRow(0);
        Cell cell = row.createCell(0);
        cell.setCellValue("Hello");
        try {
            FileOutputStream fileOut = new FileOutputStream(dirFile);
            workbook.write(fileOut);
            fileOut.close();
        } catch (IOException e) {
            System.out.println("创建excel文件时发生错误：" + e.getMessage());
        }
        return new File(dirFile);
    }

    public static File createPpt(String dirFile) {
        // 创建一个新的PPT文档
        XMLSlideShow ppt = new XMLSlideShow();

        // 创建一个空白的幻灯片
        XSLFSlide slide = ppt.createSlide();

        // 在幻灯片上添加一个标题
        XSLFTextShape title = slide.createTextBox();
        title.setAnchor(new Rectangle2D.Double(50, 50, 500, 50));
        XSLFTextParagraph paragraph = title.addNewTextParagraph();
        XSLFTextRun run = paragraph.addNewTextRun();
        run.setText("Hello, World!");
        run.setFontSize(24.0);

        // 保存PPT文件
        try (FileOutputStream out = new FileOutputStream(dirFile)) {
            ppt.write(out);
            System.out.println("PPT generated successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new File(dirFile);
    }

    /**
     * file转MultipartFile
     *
     * @param file file
     * @return MultipartFile
     */
    public static MultipartFile fileToMultipartFile(File file) {
        return fileToMultipartFile(file, file.getName());

    }

    public static MultipartFile fileToMultipartFile(File file, String fileName) {
        MultipartFile result = null;
        if (null != file) {
            try (FileInputStream input = new FileInputStream(file)) {
                String mimeType = Files.probeContentType(file.toPath());
                result = new MockMultipartFile(file.getName().concat("temp"), fileName, mimeType, input);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 获取文件扩展名，不带 .
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /**
     * Java文件操作 获取不带扩展名的文件名
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }

    public static String getDocumentType(String suffix) {
        String word = "txt doc docx";
        List<String> wordList = Arrays.asList(word.split(" "));
        String ppt = "ppt pps pptx";
        List<String> pptList = Arrays.asList(ppt.split(" "));
        String excel = "xlsx xls";
        List<String> excelList = Arrays.asList(excel.split(" "));
        for (String s : wordList) {
            if (suffix.equals(s)) return "word";
        }
        for (String s : pptList) {
            if (suffix.equals(s)) return "ppt";
        }
        for (String s : excelList) {
            if (suffix.equals(s)) return "excel";
        }
        return null;
    }
}
